package com.jgdt.tools.decrypt.rest;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.jgdt.tools.decrypt.annotation.Encrypt;
import com.jgdt.tools.decrypt.config.EncryptProperties;
import com.jgdt.tools.decrypt.utils.AESUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * <p>
 * 执行加密的切面类
 * </p>
 *
 * @author chang.zhou
 * @version $
 * @date Created in 2021/6/3 14:03
 */
@ControllerAdvice
@EnableConfigurationProperties({EncryptProperties.class})
public class EncryptResponse implements ResponseBodyAdvice<Rest> {
    Logger logger = LoggerFactory.getLogger(EncryptResponse.class);

    private EncryptProperties encryptProperties;
    private ObjectMapper objectMapper;

    public EncryptResponse(EncryptProperties encryptProperties) {
        this.encryptProperties = encryptProperties;
        this.objectMapper = new ObjectMapper();
    }

    /**
     * 只对加了 Encrypt 的接口做加密处理
     * @param methodParameter
     * @param aClass
     * @return
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return methodParameter.hasMethodAnnotation(Encrypt.class);
    }

    @Override
    public Rest beforeBodyWrite(Rest rest, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        byte[] bytes = this.encryptProperties.getKey().getBytes();
        try {
            if(rest.getMessage() != null){
                rest.setMessage(AESUtil.encrypt(rest.getMessage().getBytes(),bytes));
            }
            if(rest.getData() != null){
                rest.setData(AESUtil.encrypt(objectMapper.writeValueAsBytes(rest.getData()), bytes));
            }
        }catch (Exception e){
            logger.error("EncryptResponse/Exception", e);
        }
        return rest;
    }
}
